package xutils

import (
	"fmt"
	"gitee.com/igolang/pkg/xjson"
	"github.com/axgle/mahonia"
	"github.com/thinkeridea/go-extend/exnet"
	"io/ioutil"
	"net"
	"net/http"
	"time"
)

func ServerIP() (ip net.IP) {
	ifaces, err := net.Interfaces()
	if err != nil {
		return
	}
	for _, iface := range ifaces {
		if iface.Flags&net.FlagUp == 0 {
			continue
		}
		if iface.Flags&net.FlagLoopback != 0 {
			continue
		}
		addrs, err := iface.Addrs()
		if err != nil {
			return
		}
		for _, addr := range addrs {
			ip := getIpFromAddr(addr)
			if ip == nil {
				continue
			}

			return ip
		}
	}

	return
}

func getIpFromAddr(addr net.Addr) net.IP {
	var ip net.IP
	switch v := addr.(type) {
	case *net.IPNet:
		ip = v.IP
	case *net.IPAddr:
		ip = v.IP
	}
	if ip == nil || ip.IsLoopback() {
		return nil
	}
	ip = ip.To4()
	if ip == nil {
		return nil // not an ipv4 address
	}

	return ip
}

// ServerMac 获取本机的MAC地址
func ServerMac() string {
	str := ""
	interfaces, _ := net.Interfaces()
	if len(interfaces) == 0 {
		return str
	}
	for _, v := range interfaces {
		if v.HardwareAddr.String() != "" {
			str = v.HardwareAddr.String()
			break
		}
	}
	return str
}

func ClientIp(r *http.Request) string {
	return exnet.ClientIP(r)
}

// InternalIp
// 判断是不是内网IP，仅支持IPv4
func InternalIp(in string) bool {
	if in == "::1" || in == "127.0.0.1" {
		return true
	}
	return exnet.HasLocalIPAddr(in)
}

func Ip2Location(in string) string {
	if InternalIp(in) {
		return "内网地址"
	}
	uri := fmt.Sprintf("https://whois.pconline.com.cn/ipJson.jsp?ip=%s&json=true", in)
	req, err := http.NewRequest(http.MethodGet, uri, nil)
	if err != nil {
		return "unknown"
	}
	resp, err := (&http.Client{Timeout: 5 * time.Second}).Do(req)
	if err != nil {
		return "unknown"
	}
	defer resp.Body.Close()
	b, _ := ioutil.ReadAll(resp.Body)
	addr := xjson.Get(b, "addr").ToString()
	if addr == "" {
		addr = "unknown"
	} else {
		addr = mahonia.NewDecoder("gbk").ConvertString(addr)
	}
	return addr
}

// IsLocalIp 判断是否是本机ip
func IsLocalIp(ip string) bool {
	addrs, err := net.InterfaceAddrs()
	if err != nil {
		return false
	}
	for _, addr := range addrs {
		intf, _, err := net.ParseCIDR(addr.String())
		if err != nil {
			return false
		}
		if net.ParseIP(ip).Equal(intf) {
			return true
		}
	}

	return false
}
